
#ifndef __WEBCTRL_H__
#define __WEBCTRL_H__

#pragma once

#include <atomic>
#include <thread>
#include <functional>
#include "html.h"
#include "ArgConfig.h"
#include <DNSServer.h>
#include "LEDFlash.h"

#define MAX_TRY_COUNT 10
#ifndef AUTOCFGSSID
#define AUTOCFGSSID "ESP_WIFI"
#endif
#ifndef AUTOCFGPSW
#define AUTOCFGPSW "12345678"
#endif

#ifdef USE_8266
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
using TagWebSERVER = ESP8266WebServer;
#else
#include <WiFi.h>
#include <WebServer.h>
using TagWebSERVER = WebServer;
#endif

using FunWebServerCallback = std::function<bool(const char *)>;

class CWebControl
{
    CConfig &m_config = CConfig::getSingleton();
    LEDFlash ledFlash;

protected:
    void HandleHtmlRoot()
    {
        m_ControlWebServer.send(200, "text/html", AutoConfigHTML);
    }

    void HandleHtmlContrl()
    {
        if (m_WebServerCallback)
        {
            bool bRet = m_WebServerCallback(m_ControlWebServer.arg("btn_name").c_str());
            m_ControlWebServer.send(bRet ? 200 : 500, "text/html", m_ControlWebServer.arg("btn_name").c_str());
        }
    }

    void TryConnect(const char *SSID, const char *PSW)
    {
        int tryCount = 0;
        WiFi.begin(SSID, PSW);
        while ((tryCount < MAX_TRY_COUNT) && (WiFi.status() != WL_CONNECTED))
        {
            delay(500);
            tryCount++;
        }
    }

    void HandleHtmlAutoConfig()
    {
        String ssid, psw, key, topic, sDelay /*, otaurl*/;
        ssid = m_ControlWebServer.arg("ssid");
        psw = m_ControlWebServer.arg("psw");
        key = m_ControlWebServer.arg("key");
        topic = m_ControlWebServer.arg("topic");
        sDelay = m_ControlWebServer.arg("delay");
        Serial.println(u8"保存设置");
        
        m_config.SetWifiAP(ssid);
        m_config.SetWifiPsw(psw);
        m_config.SetKey(key);
        m_config.SetTopic(topic);
        char *ptr = nullptr;
        m_config.setDelay(strtoul(sDelay.c_str(), &ptr, 10));
        m_config.SaveConfig();
        m_ControlWebServer.send(200, "text/html", "set sucessed");
        Serial.println(u8"HTML设置：ssid--" + ssid + "--|--psw--" + psw + "--|--key--" + key + "--|--topic--" + topic + "--|--topic--" + sDelay);

        Serial.println(u8"尝试连接路由器，SSID: " + ssid + "密码: " + psw);

        TryConnect(ssid.c_str(), psw.c_str());

        ESP.restart(); // 重启8266
    }

    void HandleHtmlGetConfig()
    {
        String buffer;
        m_ControlWebServer.sendHeader("ssid", m_config.GetWifiAP(buffer));
        m_ControlWebServer.sendHeader("psw", m_config.GetWifiPsw(buffer));
        m_ControlWebServer.sendHeader("key", m_config.GetKey(buffer));
        m_ControlWebServer.sendHeader("topic", m_config.GetTopic(buffer));
        uint32_t nDelay;
        m_ControlWebServer.sendHeader("delay", String(m_config.GetDelay(nDelay)));
        m_ControlWebServer.sendHeader("powerstate", String(m_config.GetDelay(nDelay)));
        m_ControlWebServer.send(200, nullptr, "");
    }

public:
    CWebControl() : m_bRun(false)
    {
    }

    ~CWebControl()
    {
        stop();
    }

    void init()
    {
        WiFi.mode(WIFI_AP_STA); // 双模式
        WiFi.setAutoReconnect(true);

        IPAddress ip, gateway, subnet;
        ip.fromString("192.168.2.1");
        gateway.fromString("192.168.2.1");
        subnet.fromString("255.255.255.0");
        WiFi.softAPConfig(ip, gateway, subnet);

        WiFi.softAP(AUTOCFGSSID);

        m_ControlWebServer.on("/", std::bind(&CWebControl::HandleHtmlRoot, this));
        m_ControlWebServer.on("/Ctrl", HTTP_GET, std::bind(&CWebControl::HandleHtmlContrl, this));
        m_ControlWebServer.on("/AutoConfig", HTTP_GET, std::bind(&CWebControl::HandleHtmlAutoConfig, this));
        m_ControlWebServer.on("/GetConfig", HTTP_HEAD, std::bind(&CWebControl::HandleHtmlGetConfig, this));
    }

    void setCallBack(FunWebServerCallback callback)
    {
        m_WebServerCallback = callback;
    }

#ifdef USE_8266

    void stop()
    {
        m_ControlWebServer.close();
        dnsServer.stop();
    }

#else

    void stop()
    {
        m_bRun = false;
        m_ControlWebServer.close();
        if (m_LoopThread.joinable())
        {
            m_LoopThread.join();
        }
    }

#endif

#ifdef USE_8266

    void run()
    {
        m_ControlWebServer.begin(80);
        const byte DNS_PORT = 53;
        dnsServer.start(DNS_PORT, "*", IPAddress().fromString("192.168.2.1"));
    }

    void loop()
    {
        ledFlash.loop();
        m_ControlWebServer.handleClient();
        dnsServer.processNextRequest();
    }

#else

    void run()
    {
        stop();
        m_bRun = true;
        m_ControlWebServer.begin(80);
        m_LoopThread = std::thread(std::bind([&]
                                             {
            while (m_bRun)
        {
            m_ControlWebServer.handleClient();
            dnsServer.processNextRequest();
        } }));
    }

    void loop()
    {
    }

#endif

private:
#ifndef USE_8266
    std::thread m_LoopThread;
#endif
    TagWebSERVER m_ControlWebServer;
    std::atomic_bool m_bRun;
    FunWebServerCallback m_WebServerCallback;
    DNSServer dnsServer; // 创建dnsServer实例
};
#endif